package cn.qu.netty.boot;

import java.lang.reflect.Parameter;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.CharsetUtil;

public class AbstractParameterResolver implements ParameterResolver {
	
	public static final String split1 = "\\&";
	public static final String split2 = "\\{";

	private final static ParameterResolver GET = new GetParameterResolver();
	private final static ParameterResolver POST = new PostParameterResolver();

	public static ParameterResolver get(HttpMethod httpMethod) {
		ParameterResolver o = null;
		switch (httpMethod) {
		case GET:
			o = GET;
			break;
		case POST:
			o = POST;
			break;
		default:
			break;
		}
		return o;
	}

	@Override
	public Object[] resolve(FullHttpRequest req, HandlerMapping handlerMapping) throws ParameterResolverException {
		try {
			String uri = URLDecoder.decode(req.uri(), CharsetUtil.UTF_8.name());
			List<Parameter> pathVarParams = handlerMapping.getPathVarParams();
			if (pathVarParams.isEmpty()) {
				Map<String, Object> map = new HashMap<>();
				if (uri.contains("?")) {
					String paramStr = uri.substring(uri.indexOf("?") + 1);
					String[] paramArr = paramStr.split(split1);
					for (String param : paramArr) {
						String[] paramNameVal = param.split("=");
						map.put(paramNameVal[0], paramNameVal[1]);
					}
				}
				List<Object> paramVals = handlerMapping.getParameterList().stream()
						.filter(param -> map.containsKey(param.getName())).map(param -> {
							return map.get(param.getName());
						}).collect(Collectors.toList());
				return paramVals.toArray(new Object[paramVals.size()]);
			} else {
				int pathVarParamCount = pathVarParams.size();
				String[] uriArr = AbstractParameterResolver.splitPath(uri);
				// 从1开始 是为了过滤掉第一个/
				int uriIgnoreParamLenth = uriArr.length - pathVarParamCount;
				Object[] paramArr = new Object[pathVarParamCount];
				for (int i = 0; i < paramArr.length; i++) {
					paramArr[i] = uriArr[i + uriIgnoreParamLenth];
				}
				return paramArr;
			}
		} catch (Exception e) {
			throw new ParameterResolverException(e);
		}
	}

	/**
	 * @Description: 构建key
	 * @Author XiaoLong.Qu
	 * @DateTime 2021年8月11日 上午9:54:23
	 * @param path
	 * @param method
	 * @return
	 */
	public static String matchKey(String path, String method) {
		path = path.endsWith("/") ? path : path + "/";
		return path + "_" + method;
	}

	/**
	 * @Description: 计算path中参数的个数
	 * @Author XiaoLong.Qu
	 * @DateTime 2021年8月11日 上午9:55:01
	 * @param path
	 * @return
	 */
	public static int countPathParam(String path) {
		String split = split1;
		if (path.contains("{")) {
			split = split2;
		}
		return path.split(split).length - 1;
	}

	/**
	 * @Description: 从一个uri exm:/uri?name=xxx&page=xx解析结果为[["name","xxx"], ["page",
	 *               "xx"]
	 * @Author XiaoLong.Qu
	 * @DateTime 2021年8月10日 下午3:30:17
	 * @param path
	 * @return
	 */
	public static List<String[]> resolveUriParam(String uri) {
		List<String[]> list = Collections.emptyList();
		if (uri.contains("?") && uri.contains("&")) {
			String resolveUriParam = uri.substring(uri.indexOf("?") + 1, uri.length());
			String[] resolveUriParamArr = resolveUriParam.split(split1);
			list = Arrays.stream(resolveUriParamArr).map(param -> param.split("=")).collect(Collectors.toList());
		}
		return list;
	}

	/**
	 * @Description: 从一个path中按顺序解析出参数 exm:/path/{name}/{page}解析结果为["name", "page"]
	 * @Author XiaoLong.Qu
	 * @DateTime 2021年8月10日 下午3:30:17
	 * @param path
	 * @return
	 */
	public static List<String> resolvePathParam(String path) {
		List<String> list = Collections.emptyList();
		if (path.contains("{")) {
			String pathVarParamStr = path.substring(path.indexOf("{"));
			pathVarParamStr = pathVarParamStr.replaceAll("/", "").replace("}", "");
			String[] pathVarParamArr = pathVarParamStr.split(split2);
			list = Arrays.stream(pathVarParamArr).collect(Collectors.toList());
		}
		return list;
	}

	/**
	 * @Description: 以/分割uri path
	 * @Author XiaoLong.Qu
	 * @DateTime 2021年8月10日 下午10:51:47
	 * @param path
	 * @return
	 */
	public static String[] splitPath(String path) {
		return path.startsWith("/") ? path.substring(1).split("/") : path.split("/");
	}

}
